package com.peas.platform.framework.mybatisplus.domain;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peas.platform.common.core.dto.BaseDto;
import com.peas.platform.framework.mybatisplus.convertor.BaseConvertor;
import com.peas.platform.framework.mybatisplus.po.BasePo;
import com.peas.platform.framework.mybatisplus.repository.BaseRepository;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @param <D>
 * @param <P>
 * @author caizhh
 */
public interface BaseDomain<D extends BaseDto, P extends BasePo> {

    int default_batch_size = 1000;

    int split_size = 100;

    BaseConvertor<D, P> getConvertor();

    BaseRepository<P> getMapper();

    Class<P> getPoClass();

    Class<D> getDtoClass();

    Class<? extends BaseRepository<P>> getRepositoryClass();

    QueryWrapper<P> buildWrapper(Map<String, Object> fieldValue);

    QueryWrapper<P> buildWrappers(Map<String, Collection<? extends Serializable>> fieldValues);

    QueryWrapper<P> buildWrapper(D condition);

    List<OrderItem> buildOrderList(String sortField, String sortType);

    List<OrderItem> buildOrderList(Page<D> page);

    /**
     * 插入一条记录（选择字段，策略插入）
     *
     * @param dto 实体对象
     * @return 成功的条数
     */
    int save(D dto);

    /**
     * 插入（批量）
     *
     * @param dtoList 实体对象集合
     * @return 成功与否
     */
    boolean saveBatch(List<D> dtoList);

    boolean saveBatchAsync(List<D> dtoList);

    boolean saveBatchAsync(List<D> dtoList, int splitSize);

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     * @return 成功与否
     */
    int removeById(Serializable id);

    /**
     * 根据实体(ID)删除
     *
     * @param dto 实体
     * @return 成功与否
     */
    int removeById(D dto);

    /**
     * 根据 dto 条件，删除记录
     *
     * @param condition 实体包装类
     * @return 成功与否
     */
    int remove(D condition);

    /**
     * 批量删除(jdbc批量提交)
     *
     * @param dtoList 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
     * @return 成功与否
     */
    boolean removeBatchByList(List<D> dtoList);

    /**
     * 批量删除(根据主键数组)
     *
     * @param idList 主键数组
     * @return 成功与否
     */
    boolean removeBatchByIds(List<? extends Serializable> idList);

    boolean removeBatchByListAsync(List<D> dtoList);

    boolean removeBatchByListAsync(List<D> dtoList, int splitSize);

    /**
     * 根据 ID 选择修改（dto中不为null会被更新）
     *
     * @param dto 实体对象
     * @return 成功与否
     */
    int updateById(D dto);

    /**
     * 根据ID 批量更新
     *
     * @param dtoList 实体对象集合
     * @return 成功与否
     */
    boolean updateBatchById(List<D> dtoList);

    boolean updateBatchByIdAsync(List<D> dtoList);

    boolean updateBatchByIdAsync(List<D> dtoList, int splitSize);

    /**
     * TableId 注解存在更新记录，否插入一条记录
     *
     * @param dto 实体对象
     * @return 成功与否
     */
    int saveOrUpdate(D dto);

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     * @return 结果
     */
    D getById(Serializable id);

    /**
     * 查询（根据ID 批量查询）
     *
     * @param idList 主键ID列表
     * @return 结果
     */
    List<D> listByIds(List<? extends Serializable> idList);

    /**
     * 查询（根据某个字段查询，比如外键）
     *
     * @param field 字段属性名（不是数据库列名）
     * @param value 字段值
     * @return 结果
     */
    List<D> listByField(String field, Serializable value);

    Page<D> pageByField(String field, Serializable value, Page<D> page);

    /**
     * 查询（根据某个字段查询，比如外键）
     *
     * @param field  字段属性名（不是数据库列名）
     * @param values 字段值集合
     * @return 结果
     */
    List<D> listByField(String field, List<? extends Serializable> values);

    Page<D> pageByField(String field, List<? extends Serializable> values, Page<D> page);

    /**
     * 查询（根据某个字段查询，比如外键）
     *
     * @param field  字段属性名（不是数据库列名）
     * @param values 字段值集合
     * @return 结果
     */
    List<D> listByField(String field, Set<? extends Serializable> values);

    Page<D> pageByField(String field, Set<? extends Serializable> values, Page<D> page);

    List<D> listByFieldAsync(String field, List<? extends Serializable> values);

    List<D> listByFieldAsync(String field, List<? extends Serializable> values, int splitSize);

    List<D> listByFieldAsync(String field, Set<? extends Serializable> values);

    List<D> listByFieldAsync(String field, Set<? extends Serializable> values, int splitSize);

    /**
     * 查询（根据 columnMap 条件）
     *
     * @param columnMap 表字段 map 对象
     * @return 结果
     */
    List<D> listByMap(Map<String, Object> columnMap);

    /**
     * 根据 condition，查询一条记录，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    D getOne(D condition);

    /**
     * 根据 condition，查询一条记录
     *
     * @param condition 实体对象封装操作类
     * @param throwEx   有多个 result 是否抛出异常
     * @return 结果
     */
    D getOne(D condition, boolean throwEx);

    /**
     * 根据 condition，查询一条记录
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    Map<String, Object> getMap(D condition);

    /**
     * 查询总记录数
     *
     * @return 结果
     */
    long count();

    /**
     * 根据 condition 条件，查询总记录数
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    long count(D condition);

    <T extends Serializable> T abs(String field, D condition);

    Page<Map<String, Object>> abs(String field, Page<D> page, D condition, String... groupField);

    <T extends Serializable> T avg(String field, D condition);

    Page<Map<String, Object>> avg(String field, Page<D> page, D condition, String... groupField);

    <T extends Serializable> T sum(String field, D condition);

    Page<Map<String, Object>> sum(String field, Page<D> page, D condition, String... groupField);

    <T extends Serializable> T max(String field, D condition);

    Page<Map<String, Object>> max(String field, Page<D> page, D condition, String... groupField);

    <T extends Serializable> T min(String field, D condition);

    Page<Map<String, Object>> min(String field, Page<D> page, D condition, String... groupField);

    void checkRepetition(String field, String value);

    /**
     * 查询所有
     *
     * @return 结果
     */
    List<D> list();

    /**
     * 查询列表
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    List<D> list(D condition);

    /**
     * 无条件分页查询
     *
     * @param page 分页对象
     * @return 结果
     */
    Page<D> page(Page<D> page);

    Page<D> page(Page<D> page, String sortField, String sortType);

    /**
     * 分页查询
     *
     * @param page      分页对象
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    Page<D> page(Page<D> page, D condition);

    Page<D> page(Page<D> page, String sortField, String sortType, D condition);

    /**
     * 分页查询
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    @Deprecated
    Page<D> page(D condition);

    /**
     * 分页查询
     *
     * @param page      分页对象
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    Page<D> page(Page<D> page, Map<String, Object> condition);

    Page<D> page(Page<D> page, String sortField, String sortType, Map<String, Object> condition);

    /**
     * 分页查询
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    @Deprecated
    Page<D> page(Map<String, Object> condition);

    /**
     * 查询所有列表
     *
     * @return 结果
     */
    List<Map<String, Object>> listMaps();

    /**
     * 查询列表
     *
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    List<Map<String, Object>> listMaps(D condition);

    /**
     * 无条件分页查询
     *
     * @param page 分页对象
     * @return 结果
     */
    Page<Map<String, Object>> pageMaps(Page<D> page);

    Page<Map<String, Object>> pageMaps(Page<D> page, String sortField, String sortType);

    /**
     * 分页查询
     *
     * @param page      分页对象
     * @param condition 实体对象封装操作类
     * @return 结果
     */
    Page<Map<String, Object>> pageMaps(Page<D> page, D condition);

    Page<Map<String, Object>> pageMaps(Page<D> page, String sortField, String sortType, D condition);

    /**
     * 分页查询
     *
     * @param page      分页对象
     * @param condition 参数Map类型
     * @return 结果
     */
    Page<Map<String, Object>> pageMaps(Page<D> page, Map<String, Object> condition);

    Page<Map<String, Object>> pageMaps(Page<D> page, String sortField, String sortType, Map<String, Object> condition);

}
